/**
 * Project of Vehicle Routing Problem with Time Windows implements 
 * some of well-known algorithms for solving VRPTW and presents new 
 * one.
 *
 * @author Michal Drobny  
 */

package execution;

import heuristic.*;
import io.AlgorithmResultWriter;
import io.SolomonInstanceReader;

import java.io.File;
import java.util.List;

import logic.algorithm.Algorithm;
import logic.algorithm.AlgorithmResult;
import logic.car.SimpleVehicleProvider;
import logic.car.Vehicle;
import logic.destination.Destination;
import logic.evaluator.EuclideanEvaluator;
import logic.restriction.capacity.IntegerCapacityRestriction;
import logic.restriction.enumeration.TimeWindowCheckingVariant;
import logic.restriction.interfaces.HasCapacity;
import logic.restriction.interfaces.HasTimeWindow;
import logic.restriction.timeWindow.LongTimeWindowRestriction;
import logic.restrictionAdapter.SimpleRestrictionAdapter;
import logic.route.SimpleRoute;
import logic.timewindow.TimeWindow;

/**
 * The main class for solving VRP instances.
 *
 * @author Michal Drobny
 * @date 5.12.2014
 */
public class Main {

	/**
	 * This field has to be set to directory that contains VRP instances.
	 */
	private static final String BENCHMARKS_DIRECTORY_PATH = "C:\\Users\\Michal\\OneDrive\\School\\VSE\\BP\\benchmarks\\Solomon_Instances\\";

	/**
	 * This field has to be set to result directory.
	 */
	private static final String RESULT_DIRECTORY_PATH = "C:\\Users\\Michal\\OneDrive\\School\\VSE\\BP\\benchmarks\\results\\";
	
	/**
	 * This field has to be set to current algorithm for executing VRP.
	 */
	private static final Algorithm algorithm = new NearestAdding();
	
	/**
	 * The main method.
	 * 
	 * @param args
	 *            The arguments
	 */
	public static void main(String[] args) {
		File initDirectory = new File(BENCHMARKS_DIRECTORY_PATH);
		if (!initDirectory.isDirectory() || !initDirectory.canRead())
			return;

		for (File groupDirectory : initDirectory.listFiles()) {

			if (!groupDirectory.isDirectory() || !groupDirectory.canRead())
				continue;

			for (File file : groupDirectory.listFiles())
				if (file.canRead() && file.isFile())
					solveSolomonInstance(file);
		}
	}

	/**
	 * Method for solving Solomon VRP instance. The instance data is stored in
	 * given parameter (type of File).
	 * 
	 * @param file The file, where data for Solomon VRP instance are stored 
	 */
	@SuppressWarnings("unchecked")
	private static void solveSolomonInstance(File file) {
		if (file == null || !file.isFile())
			return;
		
		SolomonInstanceReader reader = new SolomonInstanceReader(file);
		reader.parse();
		
		if (!reader.isParsed() || reader.getDestinations().isEmpty() || reader.getVehicles().isEmpty())
			return;
		
		List<Destination> destinations = reader.getDestinations();
		List<Vehicle> vehicles = reader.getVehicles();
		String problemID = reader.getProblemID();
		
		SimpleRestrictionAdapter restrictionAdapter = new SimpleRestrictionAdapter();
		
		int vehicleCapacity = ((HasCapacity<Integer>)vehicles.get(0)).getCapacity();
		restrictionAdapter.addRestriction(new IntegerCapacityRestriction(vehicleCapacity));
		
		TimeWindow<Long> timeWindow = ((HasTimeWindow<Long>)destinations.get(0)).getTimeWindow();
		LongTimeWindowRestriction timeRestriction = new LongTimeWindowRestriction(
				timeWindow, 
				0L, 
				new EuclideanEvaluator(),
				TimeWindowCheckingVariant.LAZY,
				true);
		restrictionAdapter.addRestriction(timeRestriction);
		
		
		AlgorithmResult result = algorithm.compute(
				new SimpleRoute(destinations), 
				destinations.get(0), 
				new EuclideanEvaluator(), 
				restrictionAdapter,
				new SimpleVehicleProvider(vehicles));
		
		AlgorithmResultWriter.writeAlgorithmResult(
				RESULT_DIRECTORY_PATH, 
				problemID + "_" + String.valueOf(destinations.size() - 1), 
				result);
	}
}